Для того, чтобы создавать какое-либо системное или прикладное программное обеспечение, следует изучить целевую аудиторию потенциального продукта и интересы его возможных потребителей.
Penza Street заинтересована в создании инструментов, помогающих программистам, поэтому решила провести опрос среди программистов и попытаться понять, что это за люди, и чего они хотят.
Результаты исследования представлены ниже. Не все результаты были правильно и грамотно интерпретированы, так как сама структура опроса обладана массой изъянов. Компания Penza Street не рискнула проводить второй, более качественный опрос во избежание утери доверия среди целевой аудитории.
О серьёзности некоторых выводов говорить не приходится, поэтому, надеемся, вам понравится количество юмора в статье, ибо некоторые закономерности представляют из себя откровенный бред (Но, статистически вероятный бред).
Penza Street Analitics - дочерняя организация от Penza Street Company, уникальной в своём роде компании. В чём её уникальность? Хотя бы в том, что все возможные должности в ней занимает один человек, а сама компания не закреплена ни одним правовым актом ни одной страны мира.
Так что, дорогие читатели. Павел Соломатин, приятно познакомиться.
В статье могут присутствовать циничные и даже оскорбительные для конкретных групп людей, но вполне цензурные, высказывания. Эти высказывания не отражают позицию автора, а являются лишь стереотипами, не соответствующими жизни.
Автор уточняет, что дискриминационные высказывания не касаются расового, национального и религиозного характера, что уже облегчает, если не отменяет наказание по законодательству РФ.
Наличие таких высказываний объясняется большим объёмом статьи, так как не каждый дочитает до конца, не заснув. Автор попытался будить читателей смехом и внутренним негодованием при прочтении.
Текст исследования изобилует профессиональным и простонародным жаргоном (а также результатом работы личного сленгогенератора). Поэтому для неподготовленных читателей здесь приведён краткий список непонятных терминов.
Данные, использующиеся в опросе, были собраны за август 2019 года. В данных хранятся сведения о 111 программистах.
Опрос является до сих пор открытым, можете заполнить анкету. Это очень поможет (смех из-под стола).
Программисты по себе люди замкнутые и большинстве своём разрозненные личности. Собрать их в одном месте было нелегко. Если вам когда-то повезло пройти этот опрос, то скорее всего вы относились к этим категориям людей:
Кто считает себя бородатым гуру статистики или просто не хочет вникать в вот это вот всё, может смело пропустить этот раздел.
Кто совсем ничего не хочет понимать, пусть переходит к разделу “Распределение ответов”
Кто зашёл на пять минут, пусть сразу же переходит к разделу “Найденные взаимосвязи”
Математика - это всегда не просто, поэтому начнём издалека.
В основе исследования лежит статистика как наука в её чистом виде. Субъекты исследования - программисты. Объект исследования - предпочтения и навыки программистов и прочих посетителей опроса в мире информационных технологий. В данном случае, ответы - это свойства объектов, то есть опрошенных.
Любые критерии могут быть разделены на качественные и количественные. Большинство критериев в опросе было качественными, так как не было вопросов в стиле “оцените это по шкале от 1 до 10”. В это тоже есть минус опроса - нельзя ответить на вопрос “сколько?”. Качественные признаки ещё называют номинативными.
Однако, статистика на то и наука, что умеет много чего. Например:
Для одной переменной:
Правда, как оказалось, данные вышли далеко не равномерные и не нормальные. Но статистика и это может обойти
Для двух переменных:
За первый пункт отвечает Коэфиициент корреляции Пирсона, за второй - Дисперсионный анализ, а за третий - Точный тест Фишера
Правда, все первые два теста требуют “нормальности” данных, которой в этих данных нет.
Поэтому существуют их непараметрические аналоги:
При визуализации данных будут использованы два вида графиков:
Кто не хочет вникать в то, что такое R, и как было реализовано это исследование, может смело пропускать этот раздел.
В исследовании был использован язык программирования R версии 3.6.1.
Готовый файл статьи был получен с помощью пакета RMarkdown
Для визуализации был использован пакет ggplot2, а также ggthemes. Для отображения красивых шрифтов на графиках был использован пакет extrafont
Для загрузки и выгрузки данных через формат .xlsx были использованы библиотеки readxl и writexl
Дабы не грузить читателей кодовыми вставками, весь код исследования будет записан в одном месте - здесь.
Полную версию кода исследования можно увидеть на GitHub
# rm(list = ls())
options(stringsAsFactors = TRUE)
library(readxl)
library(dplyr)
opros <- read_excel("ProgOprosEdited.xlsx")
opros <- select(opros, -number) # колонка номеров не нужна
# Функция, преобразующая набор строк в фактор (словарь)
factorise <- function(opros) {
factoring_cols <-
c(
"gender",
"status",
"processor",
"microboard",
"desctop_os",
"mobile_os",
"editor_theme",
"cycle_recursion",
"cycle",
"java_kotlin",
"zero_division",
"indexing",
"typing",
"slow_python",
"list_mutable",
"sugar",
"list_expressions",
"ternar_module",
"patterns",
"mobile_desctop",
"web",
"back_front_end",
"flask_django",
"python",
"cpp",
"javascript",
"pascal",
"csharp",
"java",
"c",
"php",
"kotlin",
"lua",
"scratch",
"basic",
"go",
"ruby",
"fasm",
"bf",
"haskel",
"pycharm",
"vscode",
"idle",
"notepad",
"notepadpp",
"wing",
"sublime",
"jupiter",
"atom",
"console",
"machine_learning",
"big_data",
"metaprog",
"quantum",
"cryptography",
"math"
)
colnames(opros)
for (string in factoring_cols) {
# print(string)
opros[[string]] <- factor(opros[[string]])
}
return(opros)
}
df_struct <- list() # список, хранящий данные о структуре данных
df_struct$numeric_vars <- # список количественных переменных
c(
"languages_number",
"editors_number",
"future_number",
"humour",
"other_opinion",
"sugar_using",
"python_discontent",
"middle_answers",
"dont_know",
"web_using",
"apple"
)
df_struct$quality_vars <- # список качественных переменных
c(
"gender",
"status",
"processor",
"microboard",
"desctop_os",
"mobile_os",
"editor_theme",
"cycle_recursion",
"cycle",
"java_kotlin",
"zero_division",
"indexing",
"typing",
"slow_python",
"list_mutable",
"sugar",
"list_expressions",
"ternar_module",
"patterns",
"mobile_desctop",
"web",
"back_front_end",
"flask_django",
"python",
"cpp",
"javascript",
"pascal",
"csharp",
"java",
"c",
"php",
"kotlin",
"lua",
"scratch",
"basic",
"go",
"ruby",
"fasm",
"bf",
"haskel",
"pycharm",
"vscode",
"idle",
"notepad",
"notepadpp",
"wing",
"sublime",
"jupiter",
"atom",
"console",
"machine_learning",
"big_data",
"metaprog",
"quantum",
"cryptography",
"math"
)
df_struct$vars <- colnames(opros) # список всех переменных
df_struct$simple_vars <- # список логически полных переменных
c(
"gender",
"status",
"processor",
"microboard",
"desctop_os",
"mobile_os",
"editor_theme",
"cycle_recursion",
"cycle",
"java_kotlin",
"zero_division",
"indexing",
"typing",
"slow_python",
"list_mutable",
"sugar",
"list_expressions",
"ternar_module",
"patterns",
"mobile_desctop",
"web",
"back_front_end",
"flask_django",
"languages_number",
"editors_number",
"future_number",
"humour",
"other_opinion",
"sugar_using",
"python_discontent",
"middle_answers",
"dont_know",
"web_using",
"apple"
)
df_struct$complex_vars <- # список сгруппированных переменных
list(
languages = c(
"python",
"cpp",
"javascript",
"pascal",
"csharp",
"java",
"c",
"php",
"kotlin",
"lua",
"scratch",
"basic",
"go",
"ruby",
"fasm",
"bf",
"haskel"
),
editors = c(
"pycharm",
"vscode",
"idle",
"notepad",
"notepadpp",
"wing",
"sublime",
"jupiter",
"atom",
"console"
),
futures = c(
"machine_learning",
"big_data",
"metaprog",
"quantum",
"cryptography",
"math"
)
)
result <- list() # список для хранения промежуточных и итоговых результатов
opros <- factorise(opros) # факторизация всех сторковых столбцов
# str(opros)
## Стадия 1. Простая предобработка и гипотезы
# Simple tables
result$simple_tables <- apply(opros, 2, function(x)
round(prop.table(table(x)), digits = 3))
# Simple Fisher Test
result$simple_fisher_test <- apply(opros, 2, function(x)
chisq.test(table(x)))
# Shapiro Test
result$shapiro_test <- lapply(opros[df_struct$numeric_vars],
function(x) shapiro.test(x))
## Стадия 2. Двойные таблицы и взаимосвязи
# Double tables
result$double_tables <- lapply(opros, function(x)
lapply(opros, function(y) round(prop.table(table(x, y)), digits = 3)))
# Check equals
# sapply(opros, function(x)
# sum(sapply(opros, function(y) all(as.vector(x) == as.vector(y)))))
# all rigth
# Double Fisher Test
result$double_fisher_test <- lapply(opros[df_struct$quality_vars], function(x)
lapply(opros[df_struct$quality_vars][sapply(opros[df_struct$quality_vars], function(z) !all(as.vector(x) == as.vector(z)))],
function(y) fisher.test(table(x, y), simulate.p.value = T)))
# Cor test Kendall
result$cor_test_kendal <- lapply(opros[df_struct$numeric_vars], function(x)
lapply(opros[df_struct$numeric_vars]
[sapply(opros[df_struct$numeric_vars], function(z) !all(as.vector(x) == as.vector(z)))],
function(y) cor.test(x, y, method = "kendall")))
# Kruskal test
result$kruskal_test <- lapply(opros[df_struct$numeric_vars], function(x)
lapply(opros[df_struct$quality_vars], function(y)
kruskal.test(x, y)))
## Исследование взаимосвязей
# Researching edges
get_edges <- function(data, level) {
df <- data.frame(x = c(), y = c(), p = c())
lapply(names(data), function(x)
lapply(names(data[[x]]), function(y)
{
if (data[[x]][[y]]$p.value < level)
if (!(paste(x, y) %in% c(apply(df, 1, function(x) paste(x["x"], x["y"])),
apply(df, 1, function(x) paste(x["y"], x["x"])))))
df <<- rbind(df, data.frame(x = x, y = y, p = data[[x]][[y]]$p.value))
}
))
df <- df[df$p < level,]
df$p_log <- abs(round(log(df$p, base = 10)))
df
}
# Removing obvious edges in Kruskal test
remove_obvious_edges <- function(data) {
obvious_edges <- list(
humour = c("gender", "status", "editor_theme"),
other_opinion = c("zero_division", "indexing", "typing"),
python_discontent = c("slow_python", "list_mutable", "sugar"),
sugar_using = c("list_expressions", "ternar_module", "patterns"),
apple = c("mobile_os", "desctop_os"),
dont_know = c("microboard", "list_expressions", "ternar_module", "patterns", "flask_django"),
web_using = c("web", "flask_django"),
middle_answers = c("processor", "desctop_os", "mobile_os", "cycle_recursion",
"cycle", "java_kotlin", "slow_python", "list_mutable", "sugar",
"mobile_desctop", "flask_django"),
languages_number = c("python", "cpp",
"javascript", "pascal", "csharp", "java", "c",
"php", "kotlin", "lua", "scratch", "basic",
"go", "ruby", "fasm", "bf", "haskel"),
editors_number = c("pycharm", "vscode", "idle", "notepad",
"notepadpp", "wing", "sublime", "jupiter",
"atom", "console"),
future_number = c("machine_learning", "big_data", "metaprog",
"quantum", "cryptography", "math")
)
answer <- data.frame(x = c(), y = c(), p = c(), p_log = c())
apply(result$important_edges$kruskal_test, 1, function(x) {
if (!(x[["x"]] %in% names(obvious_edges) &
any(sapply(unlist(obvious_edges[as.vector(x[["x"]])]), function(z) as.vector(x[["y"]]) == z)))) {
answer <<- rbind(answer, data.frame(x = c(x["x"]), y = c(x["y"]),
p = c(x["p"]), p_log = c(x["p_log"])))
}
})
row.names(answer) <- NULL
answer
}
get_all_edges <- function(level) {
result$important_edges$cor_test <<- get_edges(result$cor_test_kendal, level)
result$important_edges$fisher_test <<- get_edges(result$double_fisher_test, level)
result$important_edges$kruskal_test <<- get_edges(result$kruskal_test, level)
result$important_edges$kruskal_test <<- remove_obvious_edges(result$important_edges$kruskal_test)
# Uniting edges
result$important_edges$all <<- rbind(result$important_edges$fisher_test, result$important_edges$cor_test,
result$important_edges$kruskal_test)
result$important_edges$all$x <<- as.character(result$important_edges$all$x)
result$important_edges$all$y <<- as.character(result$important_edges$all$y)
result$important_edges$all$p <<- as.numeric(result$important_edges$all$p)
result$important_edges$all$p_log <<- as.numeric(result$important_edges$all$p_log)
result$important_edges$all
}
result$important_edges$all <- get_all_edges(0.05)
find_opros_col <- function(x) {
names(opros)[sapply(names(opros), function(y) all(as.vector(opros[[y]]) == as.vector(x)))]
}
# str(result$important_edges$all)
result$edged_vars <- lapply(opros, function(x) {
x <- find_opros_col(x)
r <- apply(result$important_edges$all[
apply(result$important_edges$all, 1, function(y)
y["x"] == x | y["y"] == x),], 1, function(y) {
ifelse(y["x"] == x, y["y"], y["x"])
})
names(r) <- NULL
r})
# result$edged_vars
result$edged_vars_list <- data.frame(var = df_struct$vars,
edged_vars = sapply(opros, function(x) {
x <- find_opros_col(x)
paste(result$edged_vars[[x]], collapse = " ")
}))
var_labels <- c(gender = "Пол",
status = "Социальный\nстатус",
languages_number = "Количество используемых языков",
editors_number = "Количество используемых редакторов",
future_number = "Количество выбранных перспективных отраслей",
humour = "Коэффциент юмора",
other_opinion = "Коэффициент другого мнения",
python_discontent = "Коэффициент недовольства питоном",
sugar_using = "Коэффициент использования синтаксического сахара",
middle_answers = "Коэффициент лояльности ответов",
dont_know = "Коэффициент незнания",
web_using = "Коэффициент использования web'а",
apple = "Коэффициент лояльности к Apple",
processor = "Выбор процессора",
microboard = "Выбор микроплаты",
desctop_os = "Выбор\nнастольной ОС",
mobile_os = "Выбор\nмобильной ОС",
editor_theme = "Выбор\nтемы редактора",
cycle_recursion = "Цикл\nили\nрекурсия",
cycle = "Выбор\nвида цикла",
java_kotlin = "Java\nили\nKotlin",
zero_division = "Мнение\nо делении\nна ноль",
indexing = "Выбор индексации",
typing = "Сколько будет\n1 + \"а\"",
slow_python = "Мнение\nо скорости\nпитона",
list_mutable = "Отношение\nк изменяемости\nсписков в питоне",
sugar = "Мнение\nо \"сахарности\"\nпитона",
list_expressions = "Использование\nсписочных\nвыражений",
ternar_module = "Использование\nтернарного\nмодуля",
patterns = "Использование\nшаблонов\nпроектирования",
mobile_desctop = "Мобильная\nразработка\nили\nдесктоп",
web = "Необходимость\nвеба",
back_front_end = "Предпочитаемая\nотрасль\nвеба",
flask_django = "Flask\nили\nDjango",
python = "Использование\nPython",
cpp = "Использование\nC++",
javascript = "Использование\nJavaScript",
pascal = "Использование\nPascal",
csharp = "Использование\nC#",
java = "Использование\nJava",
c = "Использование\nC",
php = "Использование\nPHP",
kotlin = "Использование\nKotlin",
lua = "Использование\nLua",
scratch = "Использование\nScratch",
basic = "Использование\nBasic",
go = "Использование\nGo",
ruby = "Использование\nRuby",
fasm = "Использование\nFASM",
bf = "Использование\nBrainfuck",
haskel = "Использование\nHaskel",
pycharm = "Использование\nPyCharm",
vscode = "Использование\nVisual Studio\nCode",
idle = "Использование\nIDLE",
notepad = "Использование\nБлокнота",
notepadpp = "Использование\nNotepad++",
wing = "Использование\nWing",
sublime = "Использование\nSublime Text",
jupiter = "Использование\nJupiter\nNotebook",
atom = "Использование\nAtom",
console = "Использование\nконсоли",
machine_learning = "Ожидание\nразвития\nмашинного\nобучения",
big_data = "Ожидание\nразвития\nбольших\nданных",
metaprog = "Ожидание\nразвития\nметапрограммирования",
quantum = "Ожидание\nразвития\nквантовой\nлогики",
cryptography = "Ожидание\nразвития\nкриптографии",
math = "Ожидание\nразвития\nприкладной\nматематики")
spaced_var_labels <- sapply(var_labels, function(x) gsub("\n", " ", x))
full_var_labels <- c(
python = "01. Python",
cpp = "02. C++",
javascript = "03. JavaScript",
pascal = "04. Pascal",
csharp = "05. C#",
java = "06. Java",
c = "07. C",
php = "08. PHP",
kotlin = "09. Kotlin",
lua = "10. Lua",
scratch = "11. Scratch",
basic = "12. Basic",
go = "13. Go",
ruby = "14. Ruby",
fasm = "15. FASM",
bf = "16. Brainfuck",
haskel = "17. Haskel",
pycharm = "01. PyCharm",
vscode = "02. Visual Studio\nCode",
idle = "03. IDLE",
notepad = "04. Блокнот",
notepadpp = "05. Notepad++",
wing = "06. Wing",
sublime = "07. Sublime\nText",
jupiter = "08. Jupiter\nNotebook",
atom = "09. Atom",
console = "10. Консоль",
machine_learning = "01. Машинное\nобучение",
big_data = "02. Большие\nданные",
metaprog = "03. Метапрограммирование",
quantum = "04. Квантовая\nлогика",
cryptography = "05. Криптография",
math = "06. Прикладная\nматематика"
)
var_positive_flags <- c(
languages = "Использует",
editors = "Использует",
futures = "Ожидает"
)
complex_var_labels <- c(
languages = "Популярность\nязыков\nпрограммирования",
editors = "Популярность\nредакторов\nкода",
futures = "Популярность\nвозможных\nпередовых\nотраслей"
)
spaced_complex_var_labels <- sapply(complex_var_labels, function(x) gsub("\n", " ", x))
## Отрисовка графиков
library(ggplot2)
library(extrafont)
loadfonts(device = "win")
theme_pablo <- theme(panel.background = element_rect(fill = "grey70"),
plot.background = element_rect(fill = "grey60"),
legend.background = element_rect(fill = "grey80"),
text = element_text(family = "Comic Sans MS"),
axis.text.x = element_text(angle = 30, hjust = 1))
draw_plot <- function(x, y) {
if (x %in% df_struct$numeric_vars & y %in% df_struct$numeric_vars) {
random_colors <- colors()[sample(1:length(colors()), size = 2, replace = F)]
plt <- ggplot(opros, aes(x = opros[[x]], y = opros[[y]],
size = I(5), color = I(random_colors[1])))+
geom_smooth(method = "lm", se = F, color = I(random_colors[2]), size = I(3))+
geom_point()+
scale_x_continuous(breaks = seq(1:10))+
geom_jitter()+
xlab(spaced_var_labels[x])+
ylab(spaced_var_labels[y])+
ggtitle(paste("Взаимосвязь переменных\n", spaced_var_labels[x], "и",
spaced_var_labels[y]))+
theme_pablo
}
else if (x %in% df_struct$numeric_vars & y %in% df_struct$quality_vars) {
plt <- ggplot(opros, aes(x = opros[[x]], fill = opros[[y]], color = I("black")))+
geom_histogram(alpha = 0.8, binwidth = 1)+
facet_wrap(~ opros[[y]], nrow = 3)+
xlab(spaced_var_labels[x])+
ylab("Частота")+
ggtitle(paste("Взаимосвязь переменных\n", spaced_var_labels[x], "и",
spaced_var_labels[y]))+
scale_fill_brewer(name = var_labels[y],
type = "qual", palette = sample(1:8, size=1))+
scale_x_continuous(breaks = seq(1:10))+
theme_pablo
}
else if (x %in% df_struct$quality_vars & y %in% df_struct$numeric_vars) {
plt <- ggplot(opros, aes(x = opros[[y]], fill = opros[[x]], color = I("black")))+
geom_histogram(alpha = 0.8, binwidth = 1)+
facet_wrap(~ opros[[x]], nrow = 3)+
xlab(spaced_var_labels[y])+
ylab("Количество")+
ggtitle(paste("Взаимосвязь переменных\n", spaced_var_labels[x], "и",
spaced_var_labels[y]))+
scale_fill_brewer(name = var_labels[x],
type = "qual", palette = sample(1:8, size=1))+
scale_x_continuous(breaks = seq(1:10))+
theme_pablo
}
else if (x %in% df_struct$quality_vars & y %in% df_struct$quality_vars){
plt <- ggplot(opros, aes(x = opros[[x]], fill = opros[[y]], color = I("black")))+
geom_histogram(stat = "count")+
facet_wrap(~ opros[[y]])+
xlab(spaced_var_labels[x])+
ylab("Количество")+
ggtitle(paste("Взаимосвязь переменных\n", spaced_var_labels[x], "и",
spaced_var_labels[y]))+
scale_fill_brewer(name = var_labels[y],
type = "qual", palette = sample(1:8, size=1))+
theme_pablo
}
plt
}
draw_simple_plot <- function(x) {
if (x %in% df_struct$quality_vars) {
plt <- ggplot(opros, aes(x = opros[[x]], fill = opros[[x]], color = I("black")))+
geom_histogram(stat = "count")+
xlab(spaced_var_labels[x])+
ylab("Количество")+
ggtitle(paste("Распределение переменой\n", spaced_var_labels[x]))+
scale_fill_brewer(name = var_labels[x],
type = "qual", palette = sample(1:8, size=1))+
theme_pablo
}
else if (x %in% df_struct$numeric_vars) {
random_color <- colors()[sample(1:length(colors()), size=1)]
plt <- ggplot(opros, aes(x = opros[[x]], fill = I(random_color), color = I("black")))+
geom_histogram(stat = "count")+
xlab(spaced_var_labels[x])+
ylab("Частота")+
ggtitle(paste("Распределение переменной\n", spaced_var_labels[x]))+
scale_fill_brewer(name = gsub(" ", "\n", var_labels[x]),
type = "qual", palette = sample(1:8, size=1),
guide="colourbar")+
scale_x_continuous(breaks = seq(1:10))+
theme_pablo
}
plt
}
result$simple_plots <- lapply(opros, function(x) {
x <- find_opros_col(x)
plt <- draw_simple_plot(x)
plt
})
draw_complex_plot <- function(x) {
kit <- c()
for (i in 1:length(unlist(df_struct$complex_vars[x]))) {
y <- unlist(df_struct$complex_vars[x])[i]
kit <- c(kit,
ifelse(opros[y] == var_positive_flags[x], full_var_labels[y], "none"))
}
kit <- data.frame(var = kit[kit != "none"])
kit$var <- factor(kit$var)
plt <- ggplot(kit, aes(x = var, fill = var, col = I("black")))+
geom_histogram(stat = "count")+
ggtitle(spaced_complex_var_labels[x])+
xlab(spaced_complex_var_labels[x])+
ylab("Частота")+
scale_fill_brewer(name = "Частота",
type = "qual", palette = 3)+
theme_pablo
plt
}
result$complex_plots <- list()
result$complex_plots$languages <- draw_complex_plot("languages")
result$complex_plots$editors <- draw_complex_plot("editors")
result$complex_plots$futures <- draw_complex_plot("futures")
# gsub(" ", "_", gsub("\n ", "-", draw_plot("gender", "status")$labels$title))
# result$edged_vars
df <- data.frame(x = c(), y = c())
result$important_plots <- lapply(opros, function(x) {
x <- find_opros_col(x)
lapply(opros[unlist(result$edged_vars[x])], function(y) {
y <- find_opros_col(y)
plt <- draw_plot(x, y)
# if (!(paste(x, y) %in% c(apply(df, 1, function(x) paste(x["x"], x["y"])),
# apply(df, 1, function(x) paste(x["y"], x["x"]))))) {
# df <<- rbind(df, data.frame(x = x, y = y))
# i <- gsub("\"", "", gsub(" ", "_", gsub("\n ", "-", plt$labels$title)))
# ggsave(file = paste0(getwd(), "/plots/important_plots/", i, ".png"),
# plot = plt, device = "png")}
plt})})
# Graph creating
library(igraph)
net <- list()
net$edges <- data.frame(from = result$important_edges$all$x,
to = result$important_edges$all$y,
weight = result$important_edges$all$p_log)
net$vertices <- data.frame(
id = colnames(opros),
type = ifelse(colnames(opros) %in% df_struct$numeric_vars, "numeric", "quality"))
graph <- graph.data.frame(net$edges, net$vertices, directed = F)
V(graph)$color <- ifelse(net$vertices$id %in% df_struct$numeric_vars, "orange", "skyblue")
E(graph)$width <- as.numeric(as.vector(net$edges$weight))
l <- layout.kamada.kawai(graph)
# result$egdes_graph <- plot(graph, layout= l, vertex.size = 15)Используемые в опросе данные в предобработанном виде можно скачать по ссылке
Для полноценной работы скрипта исследования следует скопировать файл данных в ту же директорию, что и файл Research.Rmd.
Всего в данных содержится 67 признаков о 111 программистах
Быстро понять структуру данных можно, ознакомившись с опросом
Рядом с переменной курсивом приведено её название в данных
В опросе было рассмотрено 17 наиболее известных ЯП (Dart не выбрал никто, в данных его нет). Каждому языку в данных соответствует переменная с его названием:
python, cpp, javascript, pascal, csharp, java, c, php, kotlin, lua, scratch, basic, go, ruby, fasm, bf, haskel
В переменных хранятся значения “Использует” или “Не использует” в зависимости от ответа
В опросе было рассмотрено 10 редакторов кода, предпочтительно для питона, включая консоль. Каждому редактору в данных соответствует переменная с его названием:
pycharm, vscode, idle, notepad, notepadpp, wing, sublime, jupiter, atom, jupyter
В переменных хранятся значения “Использует” или “Не использует” в зависимости от ответа
В качестве разгрузочного вопроса участникам опроса предлагалось ответить, какие из отраслей IT являются, по их мнению, перспективными. Предлагалось 6 отраслей: большие данные, машинное обучение, квантовая логика, криптография, метапрограммирование и прикладная математика:
big_data, machine_learning, quantum, cryptography, metaprog, math
В переменных хранятся значения “Ожидает” или “Не ожидает” в зависимости от ответа
Самым большим инструментарием по обработке данных статистика имеет для количественных переменных. Однако, структура опроса была такова, что очевидными количественными переменными были всего 3. Ещё 8 были получены путём объединения качественных переменных.
Эти переменные обладают относительной шкалой от 0 до 10.
Ответы на все вопросы анкеты были обязательны и в некоторых местах не имели подходящего ответа, в этом есть минус опроса. Зато, в данных нет ни одного пропущенного значения.
Кому нечего делать, может пересчитать количество упомянутых переменных :)
В этом разделе представлены распределения всех переменных в графическом и табличном виде, к каждому из которых приложено возможное объяснение.
Не у всех переменных есть таблица распределения. Это сделано для того, чтобы уменьшить кровотечение из ваших глаз при лицезрении дробных величин в качестве групп разделения.
| x | Freq |
|---|---|
| Женский | 0.144 |
| Кафельный | 0.108 |
| Мужской | 0.748 |
| Выводы: |
| x | Freq |
|---|---|
| Аутсорсер | 0.009 |
| Пенсионер | 0.054 |
| Работяга | 0.099 |
| Студент | 0.117 |
| Фрилансер | 0.027 |
| Школьник | 0.694 |
| Выводы: |
Примечание:
Неоднозначность названия критерия объясняется тем, что высший балл достался бы тому, чьи ответы были бы “кафельный пол”, “пенсионер” и “нефильтрованная тема”. Психология подсказывает три возможные причины таких ответов:
Выводы:
Выводы:
Примечание:
Опрос не имел перед собой задачи оценить умственные способности программистов. В качестве понятия знания здесь взято количество ответов, которые могли бы дать самые рассудительные сотрудники ИТ.
Выводы:
| x | Freq |
|---|---|
| 1 | 0.126 |
| 2 | 0.279 |
| 3 | 0.315 |
| 4 | 0.135 |
| 5 | 0.054 |
| 6 | 0.090 |
Выводы:
Выводы:
| x | Freq |
|---|---|
| AMD | 0.243 |
| Intel | 0.559 |
| Всё равно | 0.198 |
| Выводы: |
| x | Freq |
|---|---|
| Arduino | 0.342 |
| Raspberri Pi | 0.486 |
| Не, не слышал | 0.171 |
| Выводы: |
| x | Freq |
|---|---|
| Linux | 0.216 |
| macOS | 0.063 |
| Windows | 0.514 |
| Лишь бы был комп | 0.207 |
| Выводы: |
| x | Freq |
|---|---|
| Android | 0.712 |
| iOS | 0.153 |
| Лишь бы был телефон | 0.135 |
| Выводы: |
Выводы:
| x | Freq |
|---|---|
| Не фильтрованная | 0.108 |
| Светлая | 0.144 |
| Тёмная | 0.748 |
| Выводы: |
| x | Freq |
|---|---|
| 1 | 0.459 |
| 2 | 0.261 |
| 3 | 0.198 |
| 4 | 0.045 |
| 5 | 0.018 |
| 6 | 0.009 |
| 7 | 0.009 |
Примечания:
Выводы:
Примечания:
Выводы:
| x | Freq |
|---|---|
| 1 | 0.099 |
| 2 | 0.324 |
| 3 | 0.216 |
| 4 | 0.117 |
| 5 | 0.081 |
| 6 | 0.063 |
| 7 | 0.072 |
| 8 | 0.009 |
| 9 | 0.009 |
| 10 | 0.009 |
Выводы:
Примечания:
Выводы:
| x | Freq |
|---|---|
| Когда как | 0.532 |
| Рекурсия | 0.072 |
| Цикл | 0.396 |
| Выводы: |
| x | Freq |
|---|---|
| for | 0.595 |
| while | 0.072 |
| Одинаково | 0.333 |
| Выводы: |
| x | Freq |
|---|---|
| Java | 0.342 |
| Kotlin | 0.324 |
| Не играет роли | 0.333 |
| Выводы: |
| x | Freq |
|---|---|
| Бесконечность | 0.234 |
| Ошибка | 0.649 |
| Так нельзя делать | 0.117 |
| Выводы: |
| x | Freq |
|---|---|
| С единицы | 0.045 |
| С нуля | 0.946 |
| С произвольного числа | 0.009 |
| Выводы: |
Не во всех современных языках программирования нумерация начинается с нуля. Например в R нумерация начинается с единицы, а в Паскале
(кто-то назвал его современным :) )- с произвольного числа.
| x | Freq |
|---|---|
| “1а” | 0.198 |
| 98 (1 + ord(“a”)) | 0.054 |
| Ошибка типа | 0.748 |
| Выводы: |
Примечание:
Выводы:
| x | Freq |
|---|---|
| Нормально | 0.441 |
| Побыстрее бы | 0.234 |
| Терпимо | 0.324 |
| Выводы: |
| x | Freq |
|---|---|
| Негативно | 0.027 |
| Нейтрально | 0.405 |
| Позитивно | 0.568 |
| Выводы: |
| x | Freq |
|---|---|
| Достаточно | 0.649 |
| Можно было бы послаще | 0.108 |
| Очень много сахара | 0.243 |
| Выводы: |
Примечания:
Выводы:
| x | Freq |
|---|---|
| Не знал | 0.108 |
| Не использую | 0.144 |
| Редко | 0.297 |
| Часто | 0.450 |
Выводы:
| x | Freq |
|---|---|
| Не знал о них | 0.036 |
| Нет | 0.063 |
| Редко | 0.234 |
| Часто | 0.667 |
| Выводы: |
| x | Freq |
|---|---|
| В питоне не применимы | 0.099 |
| Не знал о них | 0.405 |
| Редко | 0.396 |
| Часто | 0.099 |
| Выводы: |
Выводы:
| x | Freq |
|---|---|
| Всё равно | 0.387 |
| Десктоп | 0.387 |
| Мобильные | 0.225 |
| Выводы: |
| x | Freq |
|---|---|
| Как прилагающееся | 0.423 |
| Конечно | 0.441 |
| Нет | 0.135 |
| Выводы: |
| x | Freq |
|---|---|
| Бек-энд | 0.414 |
| Фронт-энд | 0.153 |
| Фул-стек | 0.432 |
| Выводы: |
(здесь должна была быть реклама игры про танки, но мне не заплатили)
| x | Freq |
|---|---|
| Django | 0.243 |
| Flask | 0.198 |
| Не знаю | 0.234 |
| Оба не тянут | 0.027 |
| Оба потянут | 0.297 |
| Выводы: |
Выводы:
Сначала, была принята попытка найти взаимосвязь визуально между всеми возможными комбинациями переменных. Но комбинаторика была не на стороне исследователя, ведь комбинаций было около 3000. Выбрать что-то не только статистически вероятное, но и интересное оказалось слишком сложно.
Далее была попытка визуализироввать взаимосвязь переменных в виде графа с учётом статистической значимости связей. Получилось что-то такое:
Если вам кажется, что это не очень-то понятно и наглядно, то вам не кажется. На одном графе указаны 67 вершин и 225 связей между ними. О читаемости такой информации говорить не приходится.
Последняя и итоговая попытка была реализована следующим образом. Сначала с помощью функциональной мощи языка R и статистических методов были найдены связи, которые статистически вероятно существуют.
Далее графики этих связей исследовались на предмет понятности имеющихся в них зависимостей. В итоговый документ вошли только те графики зависимостей, которые автор смог бы объяснить не только себе, но и другим. Автор оставляет за любым заинтересовавшимся право на исследование прочих, неопубликованных взаимосвязей и публикацию их в отдельном исследовании.
Поздравляю тех, кто дочитал до этого момента! Сейчас начнётся самое интересное…
И ещё. Если названии графика написано: “Взаимосвязь переменных A и B”, то это не значит, что A зависит от B, или B зависит от A. Направление зависимости может быть любым, а также этой взаимосвязи может не существовать вообще :D Но автор старался подобрать статистически вероятные зависимости.
Статистическая вероятность существования взаимосвязей проверялась с помощью точного критерия Фишера, корреляции Кендала и критерия Краскела-Уолесса. Статистически вероятной считалась связь, p-уровень значимости которой меньше 0,05.
| Java | Kotlin | Не играет роли | |
|---|---|---|---|
| Использует | 0.009 | 0.099 | 0.000 |
| Не использует | 0.333 | 0.225 | 0.333 |
Выводы:
| Аутсорсер | Пенсионер | Работяга | Студент | Фрилансер | Школьник | |
|---|---|---|---|---|---|---|
| Java | 0.000 | 0.018 | 0.063 | 0.009 | 0.018 | 0.234 |
| Kotlin | 0.009 | 0.009 | 0.018 | 0.090 | 0.009 | 0.189 |
| Не играет роли | 0.000 | 0.027 | 0.018 | 0.018 | 0.000 | 0.270 |
Выводы:
| Бек-энд | Фронт-энд | Фул-стек | |
|---|---|---|---|
| Java | 0.117 | 0.090 | 0.135 |
| Kotlin | 0.117 | 0.018 | 0.189 |
| Не играет роли | 0.180 | 0.045 | 0.108 |
Выводы:
| Arduino | Raspberri Pi | Не, не слышал | |
|---|---|---|---|
| Java | 0.162 | 0.144 | 0.036 |
| Kotlin | 0.072 | 0.234 | 0.018 |
| Не играет роли | 0.108 | 0.108 | 0.117 |
Выводы:
| Не фильтрованная | Светлая | Тёмная | |
|---|---|---|---|
| Java | 0.036 | 0.063 | 0.243 |
| Kotlin | 0.018 | 0.009 | 0.297 |
| Не играет роли | 0.054 | 0.072 | 0.207 |
Выводы:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
|---|---|---|---|---|---|---|---|---|---|---|
| Java | 0.036 | 0.099 | 0.090 | 0.018 | 0.009 | 0.045 | 0.036 | 0.000 | 0.009 | 0.000 |
| Kotlin | 0.000 | 0.090 | 0.063 | 0.054 | 0.045 | 0.018 | 0.036 | 0.009 | 0.000 | 0.009 |
| Не играет роли | 0.063 | 0.135 | 0.063 | 0.045 | 0.027 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
Выводы:
| 0 | 2.5 | 5 | 7.5 | 10 | |
|---|---|---|---|---|---|
| Java | 0.171 | 0.099 | 0.054 | 0.009 | 0.009 |
| Kotlin | 0.180 | 0.117 | 0.009 | 0.000 | 0.018 |
| Не играет роли | 0.081 | 0.117 | 0.054 | 0.072 | 0.009 |
Выводы:
| Не фильтрованная | Светлая | Тёмная | |
|---|---|---|---|
| AMD | 0.036 | 0.000 | 0.207 |
| Intel | 0.036 | 0.081 | 0.441 |
| Всё равно | 0.036 | 0.063 | 0.099 |
Примечания:
Выводы:
| 0 | 2.5 | 5 | 7.5 | 10 | |
|---|---|---|---|---|---|
| AMD | 0.126 | 0.063 | 0.054 | 0.000 | 0.000 |
| Intel | 0.252 | 0.216 | 0.027 | 0.036 | 0.027 |
| Всё равно | 0.054 | 0.054 | 0.036 | 0.045 | 0.009 |
Выводы:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
|---|---|---|---|---|---|---|---|
| Бек-энд | 0.234 | 0.117 | 0.063 | 0.000 | 0.000 | 0.000 | 0.000 |
| Фронт-энд | 0.054 | 0.036 | 0.018 | 0.018 | 0.009 | 0.009 | 0.009 |
| Фул-стек | 0.171 | 0.108 | 0.117 | 0.027 | 0.009 | 0.000 | 0.000 |
Выводы:
| Бек-энд | Фронт-энд | Фул-стек | |
|---|---|---|---|
| Использует | 0.063 | 0.036 | 0.216 |
| Не использует | 0.351 | 0.117 | 0.216 |
Выводы:
| Бек-энд | Фронт-энд | Фул-стек | |
|---|---|---|---|
| Использует | 0.000 | 0.000 | 0.054 |
| Не использует | 0.414 | 0.153 | 0.378 |
Выводы:
| Бек-энд | Фронт-энд | Фул-стек | |
|---|---|---|---|
| Использует | 0.018 | 0.036 | 0.081 |
| Не использует | 0.396 | 0.117 | 0.351 |
Выводы:
| Как прилагающееся | Конечно | Нет | |
|---|---|---|---|
| Использует | 0.099 | 0.216 | 0.000 |
| Не использует | 0.324 | 0.225 | 0.135 |
Выводы:
| 0 | 2 | 4 | 6 | 8 | 10 | |
|---|---|---|---|---|---|---|
| Использует | 0.000 | 0.027 | 0.009 | 0.081 | 0.135 | 0.063 |
| Не использует | 0.072 | 0.171 | 0.072 | 0.144 | 0.135 | 0.090 |
Выводы:
| 0 | 2 | 4 | 6 | 8 | 10 | |
|---|---|---|---|---|---|---|
| Использует | 0.009 | 0.018 | 0.000 | 0.000 | 0.00 | 0.000 |
| Не использует | 0.063 | 0.180 | 0.081 | 0.225 | 0.27 | 0.153 |
Выводы:
| 0 | 2 | 4 | 6 | 8 | 10 | |
|---|---|---|---|---|---|---|
| Использует | 0.000 | 0.000 | 0.000 | 0.000 | 0.00 | 0.027 |
| Не использует | 0.072 | 0.198 | 0.081 | 0.225 | 0.27 | 0.126 |
Выводы:
| 0 | 2 | 4 | 6 | 8 | 10 | |
|---|---|---|---|---|---|---|
| Использует | 0.036 | 0.162 | 0.054 | 0.171 | 0.234 | 0.144 |
| Не использует | 0.036 | 0.036 | 0.027 | 0.054 | 0.036 | 0.009 |
Выводы:
| Достаточно | Можно было бы послаще | Очень много сахара | |
|---|---|---|---|
| Использует | 0.090 | 0.009 | 0.090 |
| Не использует | 0.559 | 0.099 | 0.153 |
Выводы:
| Нормально | Побыстрее бы | Терпимо | |
|---|---|---|---|
| Использует | 0.063 | 0.000 | 0.063 |
| Не использует | 0.378 | 0.234 | 0.261 |
Выводы:
Оказывается, о человеке (программисте) можно многое сказать, зная его мобильную и настольную операционную систему.
Ради этой зависимости стоило делать исследование!
| Женский | Кафельный | Мужской | |
|---|---|---|---|
| Android | 0.063 | 0.045 | 0.604 |
| iOS | 0.054 | 0.009 | 0.090 |
| Лишь бы был телефон | 0.027 | 0.054 | 0.054 |
Выводы:
| Linux | macOS | Windows | Лишь бы был комп | |
|---|---|---|---|---|
| Android | 0.189 | 0.000 | 0.396 | 0.126 |
| iOS | 0.000 | 0.063 | 0.072 | 0.018 |
| Лишь бы был телефон | 0.027 | 0.000 | 0.045 | 0.063 |
Выводы:
| 0 | 3.3 | 6.7 | |
|---|---|---|---|
| Android | 0.595 | 0.081 | 0.036 |
| iOS | 0.144 | 0.009 | 0.000 |
| Лишь бы был телефон | 0.054 | 0.054 | 0.027 |
Выводы:
| Linux | macOS | Windows | Лишь бы был комп | |
|---|---|---|---|---|
| 0 | 0.180 | 0.054 | 0.441 | 0.117 |
| 3.3 | 0.036 | 0.009 | 0.045 | 0.054 |
| 6.7 | 0.000 | 0.000 | 0.027 | 0.036 |
Примечания:
Выводы:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.027 | 0.117 | 0.099 | 0.054 | 0.054 | 0.036 | 0.018 | 0.009 | 0.009 | 0.009 |
| 2.5 | 0.018 | 0.144 | 0.054 | 0.045 | 0.027 | 0.018 | 0.027 | 0.000 | 0.000 | 0.000 |
| 5 | 0.027 | 0.027 | 0.027 | 0.009 | 0.000 | 0.009 | 0.018 | 0.000 | 0.000 | 0.000 |
| 7.5 | 0.009 | 0.036 | 0.027 | 0.009 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
| 10 | 0.018 | 0.000 | 0.009 | 0.000 | 0.000 | 0.000 | 0.009 | 0.000 | 0.000 | 0.000 |
Выводы:
| 0 | 1.4 | 2.9 | 4.3 | 5.7 | 7.1 | 8.6 | 10 | |
|---|---|---|---|---|---|---|---|---|
| Использует | 0.036 | 0.000 | 0.045 | 0.090 | 0.108 | 0.126 | 0.108 | 0.054 |
| Не использует | 0.036 | 0.036 | 0.045 | 0.072 | 0.117 | 0.063 | 0.063 | 0.000 |
Выводы:
| 0 | 2.5 | 5 | 7.5 | 10 | |
|---|---|---|---|---|---|
| 0 | 0.000 | 0.018 | 0.009 | 0.009 | 0.036 |
| 1.4 | 0.000 | 0.018 | 0.018 | 0.000 | 0.000 |
| 2.9 | 0.009 | 0.036 | 0.027 | 0.018 | 0.000 |
| 4.3 | 0.027 | 0.081 | 0.018 | 0.036 | 0.000 |
| 5.7 | 0.063 | 0.117 | 0.027 | 0.018 | 0.000 |
| 7.1 | 0.153 | 0.027 | 0.009 | 0.000 | 0.000 |
| 8.6 | 0.126 | 0.036 | 0.009 | 0.000 | 0.000 |
| 10 | 0.054 | 0.000 | 0.000 | 0.000 | 0.000 |
Выводы:
| 0 | 2.5 | 5 | 7.5 | 10 | |
|---|---|---|---|---|---|
| Использует | 0.324 | 0.162 | 0.018 | 0.045 | 0.018 |
| Не использует | 0.108 | 0.171 | 0.099 | 0.036 | 0.018 |
Выводы:
| 0 | 2.5 | 5 | 7.5 | 10 | |
|---|---|---|---|---|---|
| Использует | 0.081 | 0.018 | 0.009 | 0.000 | 0.000 |
| Не использует | 0.351 | 0.315 | 0.108 | 0.081 | 0.036 |
Выводы:
| Аутсорсер | Пенсионер | Работяга | Студент | Фрилансер | Школьник | |
|---|---|---|---|---|---|---|
| AMD | 0.000 | 0.009 | 0.054 | 0.009 | 0.000 | 0.171 |
| Intel | 0.009 | 0.045 | 0.027 | 0.108 | 0.027 | 0.342 |
| Всё равно | 0.000 | 0.000 | 0.018 | 0.000 | 0.000 | 0.180 |
Выводы:
| Аутсорсер | Пенсионер | Работяга | Студент | Фрилансер | Школьник | |
|---|---|---|---|---|---|---|
| Использует | 0.000 | 0.009 | 0.009 | 0.009 | 0.000 | 0.000 |
| Не использует | 0.009 | 0.045 | 0.090 | 0.108 | 0.027 | 0.694 |
Выводы:
| Аутсорсер | Пенсионер | Работяга | Студент | Фрилансер | Школьник | |
|---|---|---|---|---|---|---|
| Использует | 0.009 | 0.000 | 0.018 | 0.000 | 0.009 | 0.054 |
| Не использует | 0.000 | 0.054 | 0.081 | 0.117 | 0.018 | 0.640 |
Выводы:
| Аутсорсер | Пенсионер | Работяга | Студент | Фрилансер | Школьник | |
|---|---|---|---|---|---|---|
| Использует | 0.000 | 0.018 | 0.045 | 0.000 | 0.000 | 0.081 |
| Не использует | 0.009 | 0.036 | 0.054 | 0.117 | 0.027 | 0.613 |
Выводы:
| 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|
| Аутсорсер | 0.000 | 0.000 | 0.009 | 0.000 | 0.000 | 0.000 |
| Пенсионер | 0.009 | 0.018 | 0.009 | 0.009 | 0.000 | 0.009 |
| Работяга | 0.045 | 0.036 | 0.018 | 0.000 | 0.000 | 0.000 |
| Студент | 0.018 | 0.018 | 0.045 | 0.009 | 0.009 | 0.018 |
| Фрилансер | 0.000 | 0.000 | 0.018 | 0.009 | 0.000 | 0.000 |
| Школьник | 0.054 | 0.207 | 0.216 | 0.108 | 0.045 | 0.063 |
Выводы:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
|---|---|---|---|---|---|---|---|---|---|---|
| “1а” | 0.009 | 0.027 | 0.045 | 0.018 | 0.036 | 0.018 | 0.027 | 0.009 | 0.009 | 0.000 |
| 98 (1 + ord(“a”)) | 0.009 | 0.000 | 0.027 | 0.000 | 0.009 | 0.000 | 0.009 | 0.000 | 0.000 | 0.000 |
| Ошибка типа | 0.081 | 0.297 | 0.144 | 0.099 | 0.036 | 0.045 | 0.036 | 0.000 | 0.000 | 0.009 |
Выводы:
| “1а” | 98 (1 + ord(“a”)) | Ошибка типа | |
|---|---|---|---|
| Использует | 0.018 | 0.009 | 0.000 |
| Не использует | 0.180 | 0.045 | 0.748 |
Выводы:
| “1а” | 98 (1 + ord(“a”)) | Ошибка типа | |
|---|---|---|---|
| Использует | 0.027 | 0.027 | 0.045 |
| Не использует | 0.171 | 0.027 | 0.703 |
Выводы:
| “1а” | 98 (1 + ord(“a”)) | Ошибка типа | |
|---|---|---|---|
| Использует | 0.081 | 0.027 | 0.144 |
| Не использует | 0.117 | 0.027 | 0.604 |
Выводы:
| “1а” | 98 (1 + ord(“a”)) | Ошибка типа | |
|---|---|---|---|
| Использует | 0.063 | 0.018 | 0.072 |
| Не использует | 0.135 | 0.036 | 0.676 |
Выводы:
| С единицы | С нуля | С произвольного числа | |
|---|---|---|---|
| Женский | 0.009 | 0.135 | 0.000 |
| Кафельный | 0.027 | 0.081 | 0.000 |
| Мужской | 0.009 | 0.730 | 0.009 |
Выводы:
| Женский | Кафельный | Мужской | |
|---|---|---|---|
| Использует | 0.009 | 0.063 | 0.162 |
| Не использует | 0.135 | 0.045 | 0.586 |
Выводы:
| Женский | Кафельный | Мужской | |
|---|---|---|---|
| Использует | 0.000 | 0.027 | 0.027 |
| Не использует | 0.144 | 0.081 | 0.721 |
Выводы:
| Женский | Кафельный | Мужской | |
|---|---|---|---|
| Использует | 0.036 | 0.018 | 0.036 |
| Не использует | 0.108 | 0.090 | 0.712 |
Выводы:
| Женский | Кафельный | Мужской | |
|---|---|---|---|
| Использует | 0.000 | 0.045 | 0.108 |
| Не использует | 0.144 | 0.063 | 0.640 |
Выводы:
| Женский | Кафельный | Мужской | |
|---|---|---|---|
| Использует | 0.108 | 0.054 | 0.640 |
| Не использует | 0.036 | 0.054 | 0.108 |
Выводы:
| Женский | Кафельный | Мужской | |
|---|---|---|---|
| Использует | 0.009 | 0.054 | 0.081 |
| Не использует | 0.135 | 0.054 | 0.667 |
Выводы:
| 0 | 5 | 10 | |
|---|---|---|---|
| Женский | 0.090 | 0.036 | 0.018 |
| Кафельный | 0.099 | 0.000 | 0.009 |
| Мужской | 0.658 | 0.054 | 0.036 |
Выводы:
| Достаточно | Можно было бы послаще | Очень много сахара | |
|---|---|---|---|
| Женский | 0.099 | 0.009 | 0.036 |
| Кафельный | 0.027 | 0.027 | 0.054 |
| Мужской | 0.523 | 0.072 | 0.153 |
Выводы:
| Бек-энд | Фронт-энд | Фул-стек | |
|---|---|---|---|
| Женский | 0.063 | 0.063 | 0.018 |
| Кафельный | 0.027 | 0.009 | 0.072 |
| Мужской | 0.324 | 0.081 | 0.342 |
Выводы:
| С единицы | С нуля | С произвольного числа | |
|---|---|---|---|
| Не фильтрованная | 0.027 | 0.081 | 0.000 |
| Светлая | 0.000 | 0.135 | 0.009 |
| Тёмная | 0.018 | 0.730 | 0.000 |
Выводы:
| Не фильтрованная | Светлая | Тёмная | |
|---|---|---|---|
| Использует | 0.018 | 0.072 | 0.477 |
| Не использует | 0.090 | 0.072 | 0.270 |
Выводы:
Да когда же это кончится?!
А вот сейчас и кончится. Внимание, последний график!
| Не фильтрованная | Светлая | Тёмная | |
|---|---|---|---|
| Использует | 0.036 | 0.036 | 0.072 |
| Не использует | 0.072 | 0.108 | 0.676 |
Выводы:
Программисты, как оказалось, народ непростой. В их обществе действуют свои невидимиые постороннему, а порой и программистскому, глазу закономерности и правила поведения. На их исследование можно было бы вбухать кучу лет, но так как автор этой статьи конченный меценат и раскидивает своё время налево и направо, что ему порядком надоело, то пусть этим займётся кто-нибудь другой.
Если во время прочтения вам показалось, что автор - пожилой тролль, то вы ошибаетесь.
Тролль он достаточно молодой.
Ваш коллега по цеху программного сотворения: Павел Соломатин - главный и единственный сотрудник компании Penza Street Analitics